package com.qhx.rtkcloud.ntrip;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.*;

//@Configuration
public class moveClient {


    @Value("#{${rtk.movebindmap}}")
    public Map<String, String> movebindmap;


    @Value("${rtk.movebindport}")
    private Integer movebindport;

    public static ExecutorService executorService = Executors.newFixedThreadPool(20);
    public static Map<String, LinkedBlockingQueue<byte[]>> clientMap = new ConcurrentHashMap();
    public static Map<String,Socket> clientSocketMap = new ConcurrentHashMap();

    @Bean
    public void test() {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                ServerSocket serverSocket = null;
                try {
                    serverSocket = new ServerSocket(movebindport);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                while (true) {
                    try {
                        Socket socket = serverSocket.accept();
                        InputStream inputStream = socket.getInputStream();
                        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
                        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                        //String inputLine;
                        byte[] buffer = new byte[10240];
                        int read = inputStream.read(buffer);
                        if (read > 0) {
                            byte[] bytes = Arrays.copyOfRange(buffer, 0, read);
                            String inputLine = new String(bytes, StandardCharsets.UTF_8);
                            if (inputLine.startsWith("GET /")) {
                                String mount = null;
                                /*if (inputLine.contains(" HTTP/1.1")) {
                                    mount = inputLine.substring(inputLine.indexOf("GET /") + 5, inputLine.indexOf(" HTTP/1.1")).trim();
                                } else if (inputLine.contains(" HTTP/1.0")) {
                                    mount = inputLine.substring(inputLine.indexOf("GET /") + 5, inputLine.indexOf(" HTTP/1.0")).trim();
                                }*/
                                //guess的账号密码。根据账号密码确定挂载点
                                String usernameAndPassword = inputLine.split("Basic ")[1];
                                //此处操作是移动端发送的请求最后携带/r/n，需去掉base64才可解码
                                usernameAndPassword = usernameAndPassword.substring(0,usernameAndPassword.indexOf("=")+1);
                                byte[] decode = Base64.getDecoder().decode(usernameAndPassword);
                                usernameAndPassword = new String(decode);
                                for (String s : movebindmap.keySet()) {
                                    if (movebindmap.get(s).equals(usernameAndPassword)) {
                                        mount = s;
                                        continue;
                                    }
                                }
                                //clientMap.put(mount, new LinkedBlockingQueue<>());
                                out.println("ICY 200 OK");
                                out.flush();
                                //接受移动站发送的概率坐标,发送到本地服务(发送时间间隔不固定)
                                sendProbabilityCoordinates(socket, mount);
                                ReceiveMessage(socket, mount);
                            } else if (inputLine.startsWith("mount-")) {
                                out.println("ICY 200 OK");
                                String mount = inputLine.split("-")[1];
                                clientMap.put(mount, new LinkedBlockingQueue());
                                clientSocketMap.put(mount, socket);
                                getMessage(socket, mount);
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

    }

    //移动端发送的位置信息转发到guess服务
    private void sendProbabilityCoordinates(Socket socket, String mount) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    //获取移动站发送来的概率坐标信息
                    InputStream inputStream = socket.getInputStream();
                    byte[] buffer = new byte[10240];
                    while (true){
                        int read = inputStream.read(buffer);
                        //读取到移动站发送的概率坐标信息,发送给本地服务
                        if (read > 0) {
                            byte[] bytes = Arrays.copyOfRange(buffer, 0, read);
                            String message = new String(bytes, StandardCharsets.UTF_8);
                            System.out.println(message);
                            if (clientSocketMap.containsKey(mount)) {
                                Socket clientSocket = clientSocketMap.get(mount);
                                OutputStream outputStream = clientSocket.getOutputStream();
                                outputStream.write(bytes);
                                outputStream.flush();
                            }else {
                                Thread.sleep(2000);
                            }
                            buffer = new byte[10240];
                        }
                    }
                } catch (Exception e) {
                    try {
                        socket.close();
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                    e.printStackTrace();
                }
            }
        });
    }

    private void getMessage(Socket socket, String mount) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                InputStream inputStream = null;
                byte[] buffer = new byte[10240];
                try {
                    inputStream = socket.getInputStream();
                    while (true) {
                        int read = inputStream.read(buffer);
                        if (read > 0) {
                            if (clientMap.containsKey(mount)) {
                                byte[] bytes = Arrays.copyOfRange(buffer, 0, read);
                                System.out.println("云端接收到本地传输的数据" + new String(bytes));
                                clientMap.get(mount).offer(bytes);
                            }
                            buffer = new byte[10240];
                        }else {
                            Thread.sleep(2000);
                        }
                    }
                } catch (Exception e) {
                    try {
                        socket.close();
                        clientMap.remove(mount);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    e.printStackTrace();
                }
            }
        });
    }


    public void ReceiveMessage(Socket socket, String mount) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    OutputStream outputStream = socket.getOutputStream();
                    while (true) {
                        if (clientMap.containsKey(mount)) {
                            LinkedBlockingQueue<byte[]> queue = clientMap.get(mount);
                            byte[] take = queue.take();
                            System.out.println("-----云端发送给移动站的数据" + new String(take));
                            outputStream.write(take);
                            outputStream.flush();
                        }else {
                            Thread.sleep(2000);
                        }
                    }
                } catch (IOException | InterruptedException e) {
                    clientMap.remove(mount);
                    e.printStackTrace();
                }
            }
        });
    }
}
